/*
This is part of Screenbar, which is based in part on the Litestep
shell source code.

Copyright (C) 2008-2009 Jim Babcock
Copyright (C) 1997-2009 The LiteStep Development Team

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
#include "stdafx.h"

DragWindow::DragWindow(LayoutCacheNode *sourceNode, Point mouseOffset)
	:ScreenbarWindow(getElementName(sourceNode), sourceNode->context.window->getMonitor())
{
	this->mouseOffset = mouseOffset;
	this->alwaysOnTop = true;
	
	// Bug: if the dragElement has a different size, it will be clipped
	//      to this.
	ElementContext context = sourceNode->context;
	context.window = this;
	Rect boundingRect = sourceNode->boundingRect;
	boundingRect.left = 0;
	boundingRect.top = 0;
	
	// If the element which is being dragged defines a substitute for itself
	// to be used when dragging, use it.
	LayoutElement *rootElement = sourceNode->element->dragElement;
	if(!rootElement)
		rootElement = sourceNode->element;
	
	// Build a layout tree (from scratch).
	// TODO/FIXME: Think about what to do when branch conditions and flow
	// contents change mid-drag. In particular, we can't leave references to
	// closed windows lying around.
	//layout = rootElement->buildLayout(&elementContext, NULL);
	layout = new Layout(rootElement, context, boundingRect, "");
	layout->update();
	
	// Bug: if the dragElement has a different size, it will be clipped
	//      to this.
	width  = boundingRect.width;
	height = boundingRect.height;
	Point mousePos = getCursorPos();
	int x = mousePos.x - mouseOffset.x;
	int y = mousePos.y - mouseOffset.y;
	visibleRect = Rect(x, y, width, height);
	
	HWND parentWindow = GetDesktopWindow();
	initWindow(WS_POPUP, parentWindow);
	
	SetTimer(window, TIMER_DRAGFOLLOW, 50, NULL);
	
	SetWindowPos(window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
	show();
}

DragWindow::~DragWindow()
{
	KillTimer(window, TIMER_DRAGFOLLOW);
}

string DragWindow::getElementName(LayoutCacheNode *sourceNode)
{
	string sourceElementPrefix = sourceNode->element->prefix;
	
	string dragWindowName = getConfigString("DragElement", "", sourceElementPrefix.c_str());
	if(dragWindowName=="")
		dragWindowName = sourceElementPrefix;
	
	return dragWindowName;
}

LRESULT DragWindow::handleEvent(UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch(msg)
	{
		case WM_TIMER:
			if(wParam == TIMER_DRAGFOLLOW) {
				followCursor();
				return 0;
			}
			break;
		case WM_RBUTTONUP:
		case WM_MBUTTONUP:
		case WM_LBUTTONUP:
			dragState.cancelDrag();
			break;
	}
	
	return ScreenbarWindow::handleEvent(msg, wParam, lParam);
}

void DragWindow::followCursor()
{
	Point mousePos = getCursorPos();
	int x = mousePos.x - mouseOffset.x;
	int y = mousePos.y - mouseOffset.y;
	MoveWindow(window, x, y, width, height, true);
}
